/**
 * @class   wosh::devices::PlayerGStreamerBundle
 * @brief   \ref wosh::interfaces::devices::PlayerAudio "Audio player" implementation
 *          based on \c GStreamer library, for POSIX systems.
 *
 * 
 *
 * Most important setting of the bundle is \b DeviceOutput property, default output
 * name is \c "default", but you may define your own virtual outputs to support
 * multiple audio cards or low-level settings (sample rate, buffer size, ..).
 *
 * PlayerGStreamerBundle is designed to support multiple instances at same time,
 * this is very useful when you have multiple sound cards (they will work even at
 * same time).
 *
 * In other words: I can play a different song (and different volume) on each
 * output channel, having a multi-zone audio system; moreover I can also define
 * a set of virtual outputs as multiplexer (play same track on more channels)
 * and even play a song on all outputs at same time.
 * This is enabled by a custom configuration of the ALSA layer and multiple
 * instance of the bundle (properly configured).
 *
 *
 * \par What is GStreamer?
 *  "GStreamer is a library for constructing graphs of media-handling components.
 *   The applications it supports range from simple Ogg/Vorbis playback,
 *   audio/video streaming to complex audio (mixing) and video (non-linear editing) processing.
 *   Applications can take advantage of advances in codec and filter technology transparently.
 *   Developers can add new codecs and filters by writing a simple plugin with a clean, generic interface."
 * \see     http://gstreamer.freedesktop.org
 *
 * The bundle and its bindings have been tested using ALSA layer.
 * However it is possible to switch \c alsasink with another audio rendering layer (such as \c ossink).
 * \see     http://www.alsa-project.org
 *
 *
 *
 * \par Requirements and Installation
 *  PlayerGStreamerBundle is available for POSIX platforms only (as Linux),
 *  you need to install the \b gstreamer library.
 *
 *  Tested with:
 *   - gstreamer-0.10.19 [debian lenny package]
 *   - gstreamer-0.10.26 [debian lenny-backports package] [SUGGESTED]
 *
 *  On \c Debian based systems (such as \c Ubuntu), you may install requirements executing:
 * \verbatim
alex@linbox:/home/alex# sudo apt-get install gstreamer0.10-alsa
alex@linbox:/home/alex# sudo apt-get install gstreamer0.10-plugins-base
alex@linbox:/home/alex# sudo apt-get install gstreamer0.10-plugins-good
alex@linbox:/home/alex# sudo apt-get install libgstreamer0.10-dev
alex@linbox:/home/alex# sudo updatedb
\endverbatim
 * You must accept all related dependencies.
 *
 * G++/Linker settings are configured by \c pkgconfig tool, so it should be easy to build.
 *
 *
 * \verbatim
alex@linbox:/home/alex# gst-inspect fakesrc
alex@linbox:/home/alex# gst-inspect alsasink
\endverbatim
 * This should print out a bunch of information about this particular element.
 * If this tells you that there is "no such element or plugin", you haven't installed GStreamer correctly.
 * 
 * Next test is to play the sine tone by running (make sure volume is turned up, but not too loud):
 * \verbatim
alex@linbox:/home/alex# gst-launch audiotestsrc ! audioconvert ! audioresample ! alsasink
\endverbatim
 *
 * Once the system is ready and the library have been tested, you may include the
 * PlayerGStreamerBundle in the build, editing /src/bundles/devices/devices.pri.
 * See \ref page_configuration for more information about bundle setup.
 *
 *
 * \par Using PlayerGStreamer
 *  You may test the bundle playing an audio file:
 * \verbatim
root@wosh1:Bundles/PlayerHouse# enqueue "PATH-TO-FOLDER-or-FILENAME"
root@wosh1:Bundles/PlayerHouse# volume 6
root@wosh1:Bundles/PlayerHouse# first
\endverbatim
 *
 *
 * \par (Advanced) ALSA Hacking
 *  [..] DOLBY TO MULTICHANNEL AUDIO
 * 
 * I think ALSA is awesome, after some tests and research I was able to have my
 * integrated (N+1) dolby sound card to act as N independent sound cards, and also
 * to create virtual outputs (multiplexing).
 * All you need to do is create your own \c asoundrc configuration file.
 * My own <a href="../../src/bundles/devices/PlayerGStreamer/asoundrc-sample">asoundrc</a> is provided as sample.
 * The file should be placed in the home folder (such as <tt>/home/root</tt>) of the user (running WOSH).
 *
 *
 * @todo [..] DEVICEOUTPUT, PLAYLIST and VOLUME, ALSA STUFF
 *
 * @see     wosh::interfaces::devices::PlayerAudio
 * @see     wosh::devices:PlayerPhononBundle
 * @ingroup Devices
 ****************************************************************************
 * @version 0.8.399 $Id: PlayerGStreamerBundle.h 2824 2010-08-01 13:39:47Z alex $
 * @author  Alessandro Polo
 * @date    Released on 2009-06-04
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Bundles_Devices_PlayerGStreamer_H__
 #define __WOSH_Bundles_Devices_PlayerGStreamer_H__

 #include <core/BundleGeneric.h>

 #include <interfaces/Device.h>
 #include <interfaces/devices/PlayerAudio.h>
 #include <framework/entertainment/MediaList.h>
 #include <framework/entertainment/EntertainmentEvents.h>

 #include "IPlayerGStreamerListener.h"


namespace wosh {
 using namespace entertainment;
 namespace devices {

 #define _PlayerGStreamerBundle_NAME		"PlayerGStreamer"
 #define _PlayerGStreamerBundle_VERSION		0.8384


class PlayerGStreamerBundle :	public BundleGeneric,
								public virtual wosh::interfaces::Device,
								public virtual wosh::interfaces::devices::PlayerAudio,
								public IPlayerGStreamerListener
 {
	WOSH_BUNDLE(wosh::devices::PlayerGStreamerBundle)
	WOSH_BUNDLE_INTERFACE("wosh::interfaces::devices::PlayerAudio")
	WOSH_BUNDLE_SINGLETON(0,0)


	public:
		/**
		 * @brief   Empty constructor, init bundle and vars, Properties and Methods. May Assign device name
		 * @param name [in] optional name of the bundle
		 * @param device_name [in] output device name, 'default' is the default output for gstreamer
		 * @see     setDeviceOutput()
		 */
		PlayerGStreamerBundle( const std::string& name = "", const std::string& device_name = "default" );
		/**
		 * @brief   Empty destructor, may (synch) stop bundle and internal threads when still running
		 */
		virtual ~PlayerGStreamerBundle();


	public:
		WRESULT bundleStart();
		WRESULT bundleStop();
		WRESULT bundleDiagnostic();

		void busMessage( const Message& message, const Bus* source );

//@}
/** @name Device Interface
 * @{
 ******************************************************************************/
	public:
		wosh::interfaces::Device::DEVICE_STATE getDeviceState() const { return this->devState; }
//@}
/** @name PlayerAudio Interface - Playback
 * @{
 ******************************************************************************/
	public:
		virtual WRESULT play( const std::string& file_url );

		virtual WRESULT play( unsigned int index );

		virtual WRESULT play();

		virtual WRESULT pause();

		virtual WRESULT stop();

		virtual WRESULT first();

		virtual WRESULT next();

		virtual WRESULT prev();

		virtual WRESULT last();

//@}
/** @name PlayerAudio Interface - PlayList
 * @{
 ******************************************************************************/
	public:
		virtual WRESULT enqueue( const std::string& file_url );

		virtual WRESULT remove( unsigned int index );

		virtual WRESULT clear();

//@}
/** @name PlayerAudio Interface - Setters
 * @{
 ******************************************************************************/
	public:
		virtual WRESULT setVolume(int newVolume);

		virtual WRESULT setVolumeOffset( int volume_span );
		virtual WRESULT setMute( bool on );

		virtual WRESULT setPosition( float position_rate );
		virtual WRESULT setPositionOffset( float position_rate_offset );

		virtual void setRepeatItem( bool value );
		virtual void setRepeatPlayList( bool value );

//@}
/** @name PlayerAudio Interface - Getters
 * @{
 ******************************************************************************/
	public:
		virtual int getVolume();
		virtual bool isMuted();

		virtual bool isPlaying();

		virtual int getPlaylistCount();

//@}

		virtual WRESULT setDeviceOutput( const std::string& dev_file );

		virtual WRESULT synchWithPlayer( const std::string& device_player_name, int flags = 0 );// = PlayerGStreamer_SYNCH_NO_FLAGS );
		virtual WRESULT synchFromPlayList( const MediaList* medialist );


/** @name Getters
 * @{
 ******************************************************************************/
	public:


//@}
/** @name Player Events
 * @{
 ******************************************************************************/
 	public:
		void changed_PlayState( int state, PlayerGStreamer* source );
		void changed_Volume( int volume, bool muted, PlayerGStreamer* source );

		void changed_PlayList( const wosh::entertainment::MediaList* list, PlayerGStreamer* source );
		void changed_PlayItem( const wosh::entertainment::MediaTrack* track, PlayerGStreamer* source );
//@}
/** @name IPropertiesProviderListener interface
 * @{
 ******************************************************************************/
 	public:
		bool readingProperty( Property* property_curr, const PropertiesProvider* source );
		bool updatingProperty( bool& do_update, const Variant& value_proposed, Property& property_current, const PropertiesProvider* source );
//@}
/** @name Thread Events
 * @{
 ******************************************************************************/
 	public:
		void thread_event( Thread::THREAD_STATE thread_event, Thread* thread_source );
//@}
	protected:
		/**
		 * @brief   Raise a standard Device event (fact): Create Message and inject in BusDevices ("_Bus_Devices")
		 * @param fact [in] the fact (instance) to include in (event) Message, instance will be deleted by Bus
		 */
		void raiseEvent( MessageContent* fact );

	private:
		Response* mmDoPlayIndex( const Request* request );
		Response* mmDoPlay( const Request* request );
		Response* mmDoEnqueue( const Request* request );
		Response* mmDoRemove( const Request* request );
		Response* mmDoSetVolume( const Request* request );
		Response* mmDoSetMute( const Request* request );
		Response* mmDoSetPosition( const Request* request );
		Response* mmDoSynchWithPlayer( const Request* request );

	protected:
		BusConnector BusDevices;							///< register myself & work as Device too
		PlayerGStreamer* playerWorker;						///< real implementation
		int cPlaying;

		wosh::interfaces::Device::DEVICE_STATE devState;	///< current state of device


}; // class def

 }; // namespace devices
}; // namespace wosh

#endif //__WOSH_Bundles_Devices_PlayerGStreamer_H__
